package se.thoka.twt.client.form;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import se.thoka.twt.client.event.HasRequestSubmitHandlers;
import se.thoka.twt.client.event.RequestSubmitEvent;
import se.thoka.twt.client.event.RequestSubmitHandler;
import se.thoka.twt.client.utils.validation.HasValidationHandlers;
import se.thoka.twt.client.utils.validation.ValidationEvent;
import se.thoka.twt.client.utils.validation.ValidationHandler;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;

public class TWTForm implements IsWidget, HasValidationHandlers, ValidationHandler, HasRequestSubmitHandlers, RequestSubmitHandler, HasChangeHandlers, ChangeHandler {

	private final SimpleEventBus eventBus;
	private final Map<String, TWTFormField<?>> idFieldMap;
	private final List<TWTFormField<?>> fields;
	private Widget asWidget;
	
	public TWTForm() {
		eventBus = new SimpleEventBus();
		idFieldMap = new HashMap<String, TWTFormField<?>>();
		fields = new ArrayList<TWTFormField<?>>();
	}
	
	public void add(TWTFormField<?> field) {
		String id = field.getId();
		if (idFieldMap.containsKey(id)) {
			throw new IllegalArgumentException("A field with identifier \"" + id + "\" has already been added.");
		}
		
		field.addChangeHandler(this);
		field.addValidationHandler(this);
		field.addRequestSubmitHandler(this);
		idFieldMap.put(id, field);
		fields.add(field);
	}
	
	@Override
	public HandlerRegistration addChangeHandler(ChangeHandler handler) {
		return eventBus.addHandler(ChangeEvent.getType(), handler);
	}
	
	@Override
	public HandlerRegistration addRequestSubmitHandler(RequestSubmitHandler handler) {
		return eventBus.addHandler(RequestSubmitEvent.getType(), handler);
	}
	
	@Override
	public HandlerRegistration addValidationHandler(ValidationHandler handler) {
		return eventBus.addHandler(ValidationEvent.getType(), handler);
	}
	
	@Override
	public Widget asWidget() {
		if (asWidget == null) {
			asWidget = TWTFormRenderer.getInstance().renderForm(this);
		}
		
		return asWidget;
	}

	@Override
	public void fireEvent(GwtEvent<?> event) {
		eventBus.fireEvent(event);
	}
	
	public TWTFormField<?> getField(HasTWTFormFieldInfo info) {
		return getField(info.name());
	}
	
	public TWTFormField<?> getField(String id) {
		TWTFormField<?> result = idFieldMap.get(id);
		if (result == null) {
			throw new IllegalArgumentException("Unknown form field identifier \"" + id + "\".");
		}
		
		return result;
	}
	
	public Collection<TWTFormField<?>> getFields() {
		return fields;
	}
	
	public String getValue(HasTWTFormFieldInfo info) {
		return getValue(info.name());
	}
	
	public String getValue(String id) {
		return getField(id).getText();
	}
	
	@Override
	public void onChange(ChangeEvent event) {
		fireEvent(event);
	}
	
	@Override
	public void onSubmitRequested(RequestSubmitEvent event) {
		fireEvent(event);
	}
	
	@Override
	public void onValidationChanged(ValidationEvent event) {
		fireEvent(event);
	}
	
	public void reset() {
		for (TWTFormField<?> field : getFields()) {
			field.resetValidation();
			field.setText(null);
		}
	}
	
	public void resetValidation() {
		for (TWTFormField<?> field : getFields()) {
			field.resetValidation();
		}
	}
	
	public boolean validate() {
		boolean valid = true;
		for (TWTFormField<?> field : getFields()) {
			if (!field.validate()) {
				valid = false;
			}
		}
		
		return valid;
	}
}
